/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.deephacks.tools4j.cli;
import org.junit.Test;
import javax.validation.ValidationException;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
@SuppressWarnings("unused")
public class CliMainTest {
String stringValue = "string";
String byteString = "1";
Byte byteValue = new Byte(byteString);
String integerString = "5";
Integer integerValue = new Integer(integerString);
String floatString = "5.0";
Float floatValue = new Float(floatString);
String doubleString = "1000000000000.0";
Double doubleValue = new Double(doubleString);
String longString = "1000000000000";
Long longValue = new Long(longString);
String shortString = "120";
Short shortValue = new Short(shortString);
String booleanString = "true";
Boolean booleanValue = new Boolean(booleanString);
String timeunitEnumString = "SECONDS";
TimeUnit timeunitEnumValue = TimeUnit.SECONDS;
String urlString = "http://www.test.com";
URL urlValue = newURL(urlString);
String fileString = ".";
File fileValue = new File(fileString);
String dateString = "2010-10-10";
File cliArg1 = new File(".");
Integer cliArg2 = 1;
@Test
public void test_success() {
TestCommand command = new TestCommand();
// command
String[] args = new String[] { "commandword" };
// short opts
args = fill(args, new String[] { "-a", stringValue });
args = fill(args, new String[] { "-b", byteString });
args = fill(args, new String[] { "-c", integerString });
args = fill(args, new String[] { "-e", floatString });
args = fill(args, new String[] { "-f", doubleString });
args = fill(args, new String[] { "-g", longString });
// -h and --help is reserved for help
args = fill(args, new String[] { "-i", shortString });
// non-argumented option
args = fill(args, new String[] { "-j" });
args = fill(args, new String[] { "-k", timeunitEnumString });
args = fill(args, new String[] { "-l", urlString });
args = fill(args, new String[] { "-m", fileString });
// turn on debug
args = fill(args, new String[] { "--debug" });
// varargs
args = fill(args, new String[] { "." });
args = fill(args, new String[] { "1" });
CliMain cli = new CliMain(args);
cli.run(command);
assertThat(command.stringValue, is(stringValue));
assertThat(command.byteValue, is(byteValue));
assertThat(command.integerValue, is(integerValue));
assertThat(command.floatValue, is(floatValue));
assertThat(command.doubleValue, is(doubleValue));
assertThat(command.longValue, is(longValue));
assertThat(command.shortValue, is(shortValue));
assertThat(command.booleanValue, is(booleanValue));
assertThat(command.timeunitEnumValue, is(timeunitEnumValue));
assertThat(command.urlValue, is(urlValue));
assertThat(command.fileValue, is(fileValue));
assertThat(command.cliArg1.getAbsolutePath(), is(cliArg1.getAbsolutePath()));
assertThat(command.cliArg2, is(cliArg2));
}
@Test
public void test_command_help() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream stdout = redirectOut(out);
// short opt
String[] args = new String[] { "commandword" };
args = fill(args, new String[] { "--help" });
CliMain cli = new CliMain(args);
cli.run(new TestCommand());
String helpscreen = new String(out.toByteArray());
assertTrue(helpscreen.startsWith("usage"));
// reset out
System.setOut(stdout);
}
@Test
public void test_list_commands_help() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream stdout = redirectOut(out);
String[] args = new String[] { "" };
CliMain cli = new CliMain(args);
cli.run(new TestCommand());
String helpscreen = new String(out.toByteArray());
assertTrue(helpscreen.startsWith(Utils.AVAILABLE_CMDS_MSG));
assertTrue(helpscreen.contains("commandword"));
// reset out
System.setOut(stdout);
}
@Test
public void test_unexpected_exception() {
final IllegalStateException e = new IllegalStateException("Unexpected Exception");
final class UnexpectedExceptionCommand {
@CliCmd
public void unexpected() {
throw e;
}
}
;
String[] args = new String[] { "unexpected" };
CliMain cli = new CliMain(args);
try {
cli.run(new UnexpectedExceptionCommand());
fail("exception expected");
} catch (Exception ex) {
assertEquals(ex, e);
}
}
@Test
public void test_invalid_option_input() {
String[] args = new String[] { "commandword" };
// try double value on integer
args = fill(args, new String[] { "-c", doubleValue.toString() });
CliMain cli = new CliMain(args);
try {
cli.run(new TestCommand());
fail("Should have thrown exception");
} catch (CliException e) {
assertTrue("Wrong message: " + e.getMessage(),
e.getMessage().contains(CliException.WRONG_OPT_TYPE_MSG));
}
}
@Test
public void test_invalid_argument_input() {
String[] args = new String[] { "commandword" };
// try double value on integer
args = fill(args, new String[] { "invalid_file" });
args = fill(args, new String[] { "second_arg" });
CliMain cli = new CliMain(args);
try {
cli.run(new TestCommand());
fail("exception expected");
} catch (CliException e) {
assertTrue("Wrong message: " + e.getMessage(),
e.getMessage().contains(CliException.WRONG_ARG_TYPE_MSG));
}
}
@Test
public void test_missing_argument_input() {
String[] args = new String[] { "missing" };
final class MissingArgCommand {
@CliCmd
public void missing(@NotNull String msg) {
}
}
CliMain cli = new CliMain(args);
try {
cli.run(new MissingArgCommand());
fail("exception expected");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("wrong number of arguments"));
}
}
@Test
public void test_input_constraint_violation() {
final class ValidatedCommand {
@CliOption(shortName = "o")
@Max(10)
@Min(5)
@NotNull
private Integer opt;
@CliCmd
public void validate(@Max(10) @Min(5) @NotNull Integer arg) {
}
}
;
// success
String[] args = new String[] { "validate" };
args = fill(args, new String[] { "-o", "6" });
args = fill(args, new String[] { "6" });
CliMain cli = new CliMain(args);
try {
cli.run(new ValidatedCommand());
} catch (ValidationException e) {
fail(e.getMessage());
}
// too small opt
args = new String[] { "validate" };
args = fill(args, new String[] { "-o", "4" });
args = fill(args, new String[] { "6" });
cli = new CliMain(args);
try {
cli.run(new ValidatedCommand());
fail("Validation exception expected");
} catch (ValidationException e) {
assertTrue("Wrong message: " + e.getMessage(),
e.getMessage().contains(Validator.OPT_VIOLATION_MSG));
}
// too small arg
args = new String[] { "validate" };
args = fill(args, new String[] { "-o", "6" });
args = fill(args, new String[] { "1" });
cli = new CliMain(args);
try {
cli.run(new ValidatedCommand());
fail("Validation exception expected");
} catch (ValidationException e) {
assertTrue("Wrong message: " + e.getMessage(),
e.getMessage().contains(Validator.ARG_VIOLATION_MSG));
}
}
@Test
public void test_command_does_not_exist() {
String[] args = new String[] { "bogus" };
CliMain cli = new CliMain(args);
try {
cli.run();
} catch (CliException e) {
assertTrue("Wrong message: " + e.getMessage(),
e.getMessage().contains(CliException.COMMAND_NOT_FOUND_MSG));
}
}
@Test
public void test_xargs_command() {
String[] args = new String[] { "xargscommand", "one", "1", "2", "3"};
CliMain cli = new CliMain(args);
cli.run(new XargsCommand());
assertThat(XargsCommand.varargs[0], is("1"));
assertThat(XargsCommand.varargs[1], is("2"));
assertThat(XargsCommand.varargs[2], is("3"));
}
private static URL newURL(String urlString) {
try {
return new URL(urlString);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
String[] fill(String[] first, String[] second) {
List<String> both = new ArrayList<String>(first.length + second.length);
Collections.addAll(both, first);
Collections.addAll(both, second);
return both.toArray(new String[] {});
}
public static class XargsCommand {
public static String[] varargs;
@CliCmd
public void xargscommand(String one, String... args) {
XargsCommand.varargs = args;
}
}
public class TestCommand {
@CliOption(shortName = "a")
private String stringValue;
@CliOption(shortName = "b")
private Byte byteValue;
@CliOption(shortName = "c")
private Integer integerValue;
@CliOption(shortName = "e")
private Float floatValue;
@CliOption(shortName = "f")
private Double doubleValue;
@CliOption(shortName = "g")
private Long longValue;
@CliOption(shortName = "i")
private Short shortValue;
@CliOption(shortName = "j")
private Boolean booleanValue;
@CliOption(shortName = "k")
private TimeUnit timeunitEnumValue;
@CliOption(shortName = "l")
private URL urlValue;
@CliOption(shortName = "m")
private File fileValue;
public File cliArg1;
public Integer cliArg2;
@CliCmd
public void commandword(File cliarg1, Integer cliarg2) {
this.cliArg1 = cliarg1;
this.cliArg2 = cliarg2;
}
}
public PrintStream redirectOut(ByteArrayOutputStream out) {
PrintStream stdout = System.out;
PrintStream ps = new PrintStream(out, true);
System.setOut(ps);
return stdout;
}
}